package genetic;

public abstract class Function extends TreeNode {

	protected TreeNode[] kids;
	public abstract Function createInstance(TreeNode[] kids);
	public abstract int getNumKids();
	public abstract TreeNode createRandomInstance(TreeNode[] kids);

	public Function(TreeNode[] kids) {
		this.kids = kids;
	}

	@Override
	public void updateTotalKids() {
		this.depth = depth+1;
		totalKids = 0;
		for (TreeNode t: kids){
			t.updateTotalKids();
			this.depth = Math.max(t.depth+1, this.depth);
			totalKids = totalKids + 1 + t.getTotalNumKids();
		}

	}
	@Override
	public boolean isFunction() {
		return true;
	}
	public TreeNode[] getKids() {
		return kids;
	}

	@Override
	public TreeNode clone() {
		TreeNode[] newKids = new TreeNode[kids.length];
		for (int i = 0; i < newKids.length; i++) {
			newKids[i] = kids[i].clone();
		}
		Function f = createInstance(newKids);
		f.totalKids = totalKids;
		return f;
	}

	public void replaceChild(TreeNode child, int index){
		kids[index] = child;
	}

	@Override
	public String toString() {
		String ans = "(" + getName();
		for (int i=0; i<kids.length; i++){
			ans = ans + " " + kids[i].toString();
		}
		ans = ans+")";
		return ans;
	}

	public void setIndexes(int start, int end){		
		super.setID(start);
		int index = start+1;
		for (TreeNode t: kids){
			int tNum = t.totalKids;
			t.setIndexes(index, index+tNum+1);
			index = index+tNum+1;
		}		
	}

	public int getMaxDepth(){
		int max=0;
		for (TreeNode t: kids){
			int d = t.getMaxDepth();
			if(d > max)
				max = d;
		}
		return max+1;
	}
}
